package io.renren.membermanage.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.renren.constant.BizSystemException;
import io.renren.manage.TaskQueueManage;
import io.renren.membermanage.bo.ModelTrainParamBo;
import io.renren.membermanage.dto.*;
import io.renren.membermanage.entity.*;
import io.renren.membermanage.mappper.ModelMapper;
import io.renren.membermanage.service.*;
import io.renren.sdapi.service.StableDiffusionApiService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ModelServiceImpl extends ServiceImpl<ModelMapper, Model> implements ModelService {

    @Resource
    private SysUsersService sysUsersService;

    @Resource
    private StableDiffusionApiService stableDiffusionApiService;

    @Resource
    private ModelLabelService modelLabelService;

    @Resource
    private ModelTrainService modelTrainService;

    @Resource
    private ModelTrainDetailService modelTrainDetailService;

    @Resource
    private TaskService taskService;

    @Resource
    private ModelTrainParamService modelTrainParamService;

    @Resource
    private TaskQueueManage taskQueueManage;

    @Value("${model.upload.base.lora.path}")
    private String modelUploadBaseLoraPath;

    @Value("${model.upload.base.basic.path}")
    private String modelUploadBaseBasicPath;

    @Value("${model.picture.save.path}")
    private String modelPictureSavePath;

    @Value("${train.files.save.url}")
    private String baseDir;

    @Value("${train.log}")
    private String trainLog;

    @Value("${train.file.check}")
    private String trainFileCheck;

    private final ObjectMapper objectMapper = new ObjectMapper();

    public boolean addModel(MultipartFile picture, MultipartFile modelFile, AddModelParam param){
        Model model = BeanUtil.copyProperties(param, Model.class);
        if (this.exists(getQueryWrapper(model))) {
            throw new BizSystemException("当前上传的模型已存在！");
        }
        model.setId(IdWorker.getId());
        model.setSysModelSign(0);
        model.setCreateTime(LocalDateTime.now());
        model.setUpdateTime(LocalDateTime.now());
        model.setUploader(Long.valueOf(StpUtil.getTokenInfo().getLoginId().toString()));
        model.setCreateBy(model.getUploader());
        String modelRealName = RandomUtil.randomString(32);
        model.setModelRealName(modelRealName + ".safetensors");
        String workDic = getWorkDic();
        String filePath = "";
        File dest = getDest(param.getModelOwner(), param.getModelType(), workDic, model.getUploader(), filePath, model.getModelRealName(), modelFile.getOriginalFilename());
        filePath = dest.getPath().replace("\\","/");
        writeModel(dest, modelFile, model, filePath);
        writePicture(workDic, picture, model);
        if (model.getModelType() == 1) {
            refeshModel(model, filePath);
        }
        return this.save(model);
    }

    @Override
    public boolean addModelByTrain(MultipartFile picture, String modelName, AddModelParam param) {
        Model model = BeanUtil.copyProperties(param, Model.class);
        if (this.exists(getQueryWrapper(model))) {
            throw new BizSystemException("当前上传的模型已存在！");
        }
        model.setId(IdWorker.getId());
        model.setSysModelSign(0);
        model.setCreateTime(LocalDateTime.now());
        model.setUpdateTime(LocalDateTime.now());
        model.setUploader(Long.valueOf(StpUtil.getTokenInfo().getLoginId().toString()));
        model.setCreateBy(model.getUploader());
        model.setLabelId(null == param.getLabelId() ? null : param.getLabelId());
        String modelRealName = RandomUtil.randomString(32);
        model.setModelRealName(modelRealName + ".safetensors");
        String filePath = "";
        String workDic = getWorkDic();
        workDic = "E:/APP/";
        File dest = getDest(param.getModelOwner(), param.getModelType(), workDic, model.getUploader(), filePath, model.getModelRealName(), modelName);
        try {
            if (null == dest){
                throw new BizSystemException("文件上传失败请检查");
            }
            filePath = dest.getPath().replace("\\","/");
            // 确保目标目录存在
            dest.getParentFile().mkdirs();
            // 将文件复制到指定路径
            Path trainFilePath = Paths.get(workDic + trainFileCheck + modelName);
            Files.copy(trainFilePath, dest.toPath());
            model.setModelLink(filePath);
            String picturePath = workDic + modelPictureSavePath + picture.getOriginalFilename();
            File pictureDest = new File(picturePath);
            pictureDest.getParentFile().mkdirs();
            picture.transferTo(pictureDest);
            model.setPictureSavePath(workDic + modelPictureSavePath + picture.getOriginalFilename());
            model.setPictureVisitPath(workDic + modelPictureSavePath + picture.getOriginalFilename());
            log.info("The currently uploaded model has been created successfully, and sd is being invoked to refresh the model！path is ：{}", filePath);
            if (param.getModelType() == 1) {
                if (stableDiffusionApiService.refresh()) {
                    String loraSsOutputName = stableDiffusionApiService.getLoraSsOutputName(filePath);
                    model.setSsOutputName(loraSsOutputName);
                }
            }
        }catch (Exception e){
            throw new BizSystemException("文件上传失败请检查");
        }
        return this.save(model);
    }

    public boolean updateModel(MultipartFile picture, MultipartFile modelFile, UpdateModelParam param) {
        Model model = this.getById(param.getId());
        if (null == model){
            throw new BizSystemException("当前模型不存在！");
        }
        String modelLink = model.getModelLink();
        model= BeanUtil.copyProperties(param,Model.class);
        model.setUpdateTime(LocalDateTime.now());
        model.setUploader(Long.valueOf(StpUtil.getTokenInfo().getLoginId().toString()));
        model.setCreateBy(model.getUploader());
        model.setLabelId(null != param.getLabelId() ? param.getLabelId() : model.getLabelId());
        String workDic = getWorkDic();
        modelLink =workDic+modelLink.substring(modelLink.indexOf("sdapp"));
        //如果新上传图片需要修改图片
        if (picture != null && picture.getSize() > 0){
            //删除图片
            File file = new File(model.getPictureSavePath());
            //重新写入图片
            deleteFile(file);
            writePicture(workDic, picture, model);
        }
        //如果新上传模型需要修改模型
        if (modelFile != null && modelFile.getSize() > 0){
            String modelRealName = RandomUtil.randomString(32);
            model.setModelRealName(modelRealName + ".safetensors");
            String filePath = "";
            File dest = getDest(param.getModelOwner(), param.getModelType(), workDic, model.getUploader(), filePath, model.getModelRealName(), modelFile.getOriginalFilename());
            File file = new File(modelLink);
            filePath = dest.getPath().replace("\\","/");
            deleteFile(file);
            writeModel(dest, modelFile, model, filePath);
            if (model.getModelType() == 1) {
                refeshModel(model, filePath);
            }
//            if (StrUtil.isNotBlank(param.getLabelName())){
//                LambdaQueryWrapper<ModelLabelConnect> wrapper = new LambdaQueryWrapper<>();
//                wrapper.eq(ModelLabelConnect::getModelId, model.getId());
//                modelLabelConnectService.remove(wrapper);
//            }
        }
        return this.updateById(model);
    }

    public boolean deleteModel(Long id) {
        Model model = this.getById(id);
        File file = new File(model.getPictureSavePath());
        deleteFile(file);
        File file2 = new File(model.getModelLink());
        deleteFile(file2);
        return this.removeById(model);
    }

    public List<ModelLabel> getModelLabel(){
        return modelLabelService.list().stream().filter(c -> c.getDelFlag() == 0).toList();
    }

    public Page<Model> getList(QueryModelParam param){
        Page<Model> result = new Page<>();
        QueryWrapper<Model> query = new QueryWrapper<>();
        query.like(StrUtil.isNotBlank(param.getModelName()), "model_name", param.getModelName());
        if(!StringUtils.isEmpty(param.getModelLabelId())) {
            query.eq("label_id", param.getModelLabelId());
        }
        if (StrUtil.isNotBlank(param.getModelType())){
            query.eq( "model_type", Integer.valueOf(param.getModelType()));
        }
        query.eq("is_use", 0);
        query.eq("del_flag", 0);
        query.orderByDesc("create_time");
        if ("1".equals(param.getRadios()) || "4".equals(param.getRadios()) || "5".equals(param.getRadios())) {
            if ("1".equals(param.getRadios())){
                query.eq("sys_model_sign", 0);
                query.eq("uploader", Long.valueOf(StpUtil.getTokenInfo().getLoginId().toString()));
            }
            if ("4".equals(param.getRadios())){
                query.eq("model_owner", 3);
                query.eq("sys_model_sign", 0);
            }
            if ("5".equals(param.getRadios())){
                query.eq("sys_model_sign", 1);
            }
            result = this.page(Page.of(param.getPageNum(), param.getPageSize()), query);
            List<Model> records = result.getRecords();
            getLabelInfo(records);
            records = records.stream()
                    .skip( (param.getPageNum() - 1) * param.getPageSize())
                    .limit(param.getPageSize())
                    .peek(c -> {
                        if (StrUtil.isNotBlank(c.getPictureSavePath())){
                            // 查找最后一个斜杠的位置，这里同时考虑了Windows和Unix风格的路径分隔符
                            int lastIndex = c.getPictureSavePath().lastIndexOf('/') > -1 ? c.getPictureSavePath().lastIndexOf('/') : c.getPictureSavePath().lastIndexOf('\\');
                            String fileName = c.getPictureSavePath().substring(lastIndex + 1);
                            c.setBrowsesPath(StrUtil.isBlank(fileName) ? "" : "/test_user_1/model/picture/" + fileName);
                        }
                    })
                    .toList();
            result.setRecords(records);
        }
        if ("2".equals(param.getRadios())){
            Long deptId = sysUsersService.getById(Long.valueOf(StpUtil.getTokenInfo().getLoginId().toString())).getDeptId();
            List<Long> userSameDept = sysUsersService.getUserSameDept(deptId);
            if (CollUtil.isEmpty(userSameDept)){
                return result;
            }
            query.in("uploader", userSameDept);
            query.eq("sys_model_sign", 0);
            result = this.page(Page.of(param.getPageNum(), param.getPageSize()), query);
            List<Model> records = result.getRecords();
            getLabelInfo(records);
            records = records.stream()
                    .skip( (param.getPageNum() - 1) * param.getPageSize())
                    .limit(param.getPageSize())
                    .peek(c -> {
                        if (StrUtil.isNotBlank(c.getPictureSavePath())){
                            // 查找最后一个斜杠的位置，这里同时考虑了Windows和Unix风格的路径分隔符
                            int lastIndex = c.getPictureSavePath().lastIndexOf('/') > -1 ? c.getPictureSavePath().lastIndexOf('/') : c.getPictureSavePath().lastIndexOf('\\');
                            String fileName = c.getPictureSavePath().substring(lastIndex + 1);
                            c.setBrowsesPath(StrUtil.isBlank(fileName) ? "" : "/test_user_1/model/picture/" + fileName);
                        }
                    })
                    .toList();
            result.setRecords(records);
        }
        if ("3".equals(param.getRadios())){
            query.eq("sys_model_sign", 0);
            query.eq("uploader", Long.valueOf(StpUtil.getTokenInfo().getLoginId().toString()));
            List<Model> models = this.baseMapper.selectList(query);
            QueryWrapper<Model> ownerQuery = new QueryWrapper<>();
            ownerQuery.eq("sys_model_sign", 0);
            ownerQuery.eq("model_owner",3);
            ownerQuery.like(StrUtil.isNotBlank(param.getModelName()), "model_name", param.getModelName());
            if(!StringUtils.isEmpty(param.getModelLabelId())) {
                ownerQuery.eq("label_id", param.getModelLabelId());
            }
            if (StrUtil.isNotBlank(param.getModelType())){
                ownerQuery.eq( "model_type", Integer.valueOf(param.getModelType()));
            }
            ownerQuery.ne("uploader", Long.valueOf(StpUtil.getTokenInfo().getLoginId().toString()));
            List<Model> ownerModels = this.baseMapper.selectList(ownerQuery);
            models.addAll(ownerModels);
            QueryWrapper<Model> sysQuery = new QueryWrapper<>();
            sysQuery.eq("sys_model_sign", 1);
            if(!StringUtils.isEmpty(param.getModelLabelId())) {
                sysQuery.eq("label_id", param.getModelLabelId());
            }
            sysQuery.like(StrUtil.isNotBlank(param.getModelName()), "model_name", param.getModelName());
            if (StrUtil.isNotBlank(param.getModelType())){
                sysQuery.eq( "model_type", Integer.valueOf(param.getModelType()));
            }
            sysQuery.eq("is_use", 0);
            sysQuery.eq("del_flag", 0);
            models.addAll(this.baseMapper.selectList(sysQuery));
            if (CollUtil.isEmpty(models)){
                return result;
            }
            List<Model> sortedList = models.stream()
                    .sorted(Comparator.comparing(Model::getCreateTime).reversed())
                    .toList();
            result.setTotal(sortedList.size());
            sortedList = sortedList.stream()
                    .skip( (param.getPageNum() - 1) * param.getPageSize())
                    .limit(param.getPageSize())
                    .peek(c -> {
                        if (StrUtil.isNotBlank(c.getPictureSavePath())){
                            // 查找最后一个斜杠的位置，这里同时考虑了Windows和Unix风格的路径分隔符
                            int lastIndex = c.getPictureSavePath().lastIndexOf('/') > -1 ? c.getPictureSavePath().lastIndexOf('/') : c.getPictureSavePath().lastIndexOf('\\');
                            String fileName = c.getPictureSavePath().substring(lastIndex + 1);
                            c.setBrowsesPath(StrUtil.isBlank(fileName) ? "" : "/test_user_1/model/picture/" + fileName);
                        }
                    })
                    .toList();
            getLabelInfo(sortedList);
            result.setRecords(sortedList);
        }
        return result;
    }

    private QueryWrapper<Model> getQueryWrapper(Model param){
        QueryWrapper<Model> query = new QueryWrapper<>();
        query.eq(StrUtil.isNotBlank(param.getModelName()), "model_name", param.getModelName());
        query.eq(param.getModelType() > 0, "model_type", param.getModelType());
        query.eq(param.getModelOwner() > 0, "model_owner", param.getModelOwner());
        query.eq("del_flag", 0);
        query.eq("is_use", 0);
        query.eq("sys_model_sign", 0);
        return query;
    }

    public boolean excuteTrain(ModelTrainParamBo bo){
        Model model = this.baseMapper.selectById(bo.getModelId());
        if (null == model || StrUtil.isBlank(model.getModelLink())){
            throw new BizSystemException(500, "您选择的模型存在异常！");
        }
        String workDic = System.getProperty("user.dir");
        workDic = workDic.substring(0,workDic.length()-1);
        workDic = workDic.substring(0,workDic.lastIndexOf("\\"));
        //根据userId获取上传的文件
        String dic = workDic + baseDir + bo.getUserId();
        File directory = new File(dic);
        // 检查该路径是否是一个目录
        if (directory.isDirectory()) {
            // 获取该目录下的所有文件和子目录
            File[] files = directory.listFiles();
            if (files != null) {
                // 遍历文件数组
                for (File file : files) {
                    // 检查是否是文件而不是目录
                    if (!file.isFile()) {
                        throw new BizSystemException(500, "请确认您上传的文件中没有非文件的内容");
                    }
                }
            } else {
                throw new BizSystemException(500, "无法读取目录内容，可能是权限问题或目录为空。");
            }
        } else {
            throw new BizSystemException(500, "路径不是一个有效的目录。");
        }
        try {
            long versionNum = modelTrainService.count(new QueryWrapper<ModelTrain>().eq("input_output_name",bo.getOutput_name()));
            versionNum++;
            LambdaQueryWrapper<ModelTrainParam> paramWrapper = new LambdaQueryWrapper<>();
            paramWrapper.eq(ModelTrainParam::getDelFlag, "0");
            Map<String, String> map = modelTrainParamService.list(paramWrapper).stream().collect(Collectors.toMap(ModelTrainParam::getParamName, ModelTrainParam::getParamValue));
            ModelTrainParamDto param = generateModelTrainParam(map);
            param.setPretrained_model_name_or_path(model.getModelLink());
            param.setOutput_name(bo.getOutput_name() + "_V" + versionNum);
            param.setMax_train_epochs(bo.getMax_train_epochs());
            param.setTrain_batch_size(bo.getTrain_batch_size());
            param.setSample_prompts(bo.getSample_prompts()+",  --w 512  --h 768  --l 7  --s 24  --d 1337");
            param.setTrain_data_dir(dic);
            param.setSave_every_n_epochs(bo.getSave_every_n_epochs());
            String paramStr = objectMapper.writeValueAsString(param);
            ModelTrain data = new ModelTrain();
            data.setId(IdWorker.getId());
            data.setUserId(bo.getUserId());
            data.setCreateTime(LocalDateTime.now());
            data.setUpdateTime(LocalDateTime.now());
            data.setOutputName(bo.getOutput_name()+"_V"+versionNum);
            data.setInputOutputName(bo.getOutput_name());
            data.setTrainParam(paramStr);
            data.setStatus(3);
            boolean save = modelTrainService.save(data);
            if (save){
                Runnable task = taskService.createTask(data);
                taskQueueManage.submitTask(task);
                log.info("----------------The submission queue was successful. The primary key identifier for training ： {}", data.getId());
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BizSystemException(500, "创建训练任务失败");
        }
        return true;
    }

    public String getSchedule(String taskId){
        String workDic = System.getProperty("user.dir");
        workDic = workDic.substring(0,workDic.length()-1);
        workDic = workDic.substring(0,workDic.lastIndexOf("\\"));
        Path logFilePath = Paths.get(workDic + trainLog);
        String taskCreatedPattern = "Task " + taskId + " created";
        Pattern epochPattern = Pattern.compile("epoch (\\d+)/(\\d+)");
        String successFlag = "Training finished";
        String failedFlag = "Training failed";
        double percentage = 0.0;
        try (BufferedReader reader = Files.newBufferedReader(logFilePath, StandardCharsets.UTF_8)) {
            String line;
            boolean identifierFound = false;
            while ((line = reader.readLine()) != null) {
                    if (line.contains(taskCreatedPattern)) {
                    identifierFound = true;
                }
                if (identifierFound){
                    Matcher matcher = epochPattern.matcher(line);
                    if (matcher.find()) {
                        int currentEpoch = Integer.parseInt(matcher.group(1));
                        int totalEpochs = Integer.parseInt(matcher.group(2));
                        percentage = ((double) currentEpoch / totalEpochs) * 100;
                    }
                    if (line.contains(successFlag)){
                        break;
                    }
                    if (line.contains(failedFlag)){
                        QueryWrapper<ModelTrain> wrapper = new QueryWrapper<>();
                        wrapper.eq("task_id", taskId);
                        ModelTrain update = modelTrainService.getOne(wrapper);
                        update.setStatus(9);
                        update.setUpdateTime(LocalDateTime.now());
                        modelTrainService.updateById(update);
                        return "训练失败";
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return String.format("%.2f%%", percentage);
    }

    public Page<ModelTrain> getModelTrain(QueryModelTrainDto dto){
        QueryWrapper<ModelTrain> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", dto.getUserId());
        wrapper.eq(null != dto.getStatus(), "status", dto.getStatus());
        Page<ModelTrain> page = new PageDTO<>(dto.getPageNum(), dto.getPageSize());
        return modelTrainService.page(page, wrapper);
    }
    public List<ModelTrainDetail> getModelTrainDetail(QueryModelTrainDetailDto dto){
        QueryWrapper<ModelTrainDetail> wrapper = new QueryWrapper<>();
        wrapper.eq(null != dto.getModelTrainId(), "model_train_id", dto.getModelTrainId());
        return modelTrainDetailService.list(wrapper);
    }

    private String getWorkDic(){
        String workDic = System.getProperty("user.dir");
        workDic = workDic.substring(0,workDic.length()-1);
        workDic = workDic.substring(0,workDic.lastIndexOf("\\"));
        workDic = workDic.replace("\\","/");
        return workDic;
    }

    private File getDest(Integer modelOwner, Integer modelType, String workDic, Long uploader, String filePath, String modelRealName,
                         String modelFileName){
        File dest = null;
        if(modelOwner == 1){
            Map<Long, String> map1 = sysUsersService.list().stream().collect(Collectors.toMap(SysUser::getId, SysUser::getUsername));
            String memberName = map1.get(uploader);
            if (modelType == 1) {
                filePath = workDic + modelUploadBaseLoraPath + memberName + "/" + modelRealName + "." + StrUtil.subAfter(modelFileName, ".", true);
            }
            if (modelType == 2) {
                filePath = workDic + modelUploadBaseBasicPath + memberName + "/" + modelRealName + "." + StrUtil.subAfter(modelFileName, ".", true);
            }
            dest = new File(filePath);
        }
        if (modelOwner == 2){
            if (modelType == 1) {
                filePath = workDic + modelUploadBaseLoraPath + "team/" + modelRealName + "." + StrUtil.subAfter(modelFileName, ".", true);
            }
            if (modelType == 2) {
                filePath = workDic + modelUploadBaseBasicPath + "team/" + modelRealName + "." + StrUtil.subAfter(modelFileName, ".", true);
            }
            dest = new File(filePath);
        }
        if (modelOwner == 3){
            if (modelType == 1) {
                filePath = workDic + modelUploadBaseLoraPath + "share/" + modelRealName + "." + StrUtil.subAfter(modelFileName, ".", true);
            }
            if (modelType == 2) {
                filePath = workDic + modelUploadBaseBasicPath + "share/" + modelRealName + "." + StrUtil.subAfter(modelFileName, ".", true);
            }
            dest = new File(filePath);
        }
        return dest;
    }

    private void writeModel(File dest, MultipartFile modelFile, Model model, String filePath){
        try{
            if (null == dest){
                throw new BizSystemException("文件上传失败请检查");
            }
            // 确保目标目录存在
            dest.getParentFile().mkdirs();
            // 将文件写入指定路径
            modelFile.transferTo(dest);
            model.setModelLink(filePath);
        }catch (Exception e){
            throw new BizSystemException("模型文件写入指定目录时发生错误！");
        }
    }

    private void writePicture(String workDic, MultipartFile picture, Model model){
        try{
            String picturePath = workDic + modelPictureSavePath + picture.getOriginalFilename();
            File pictureDest = new File(picturePath);
            pictureDest.getParentFile().mkdirs();
            picture.transferTo(pictureDest);
            model.setPictureSavePath(workDic + modelPictureSavePath + picture.getOriginalFilename());
            model.setPictureVisitPath(workDic + modelPictureSavePath + picture.getOriginalFilename());
        }catch (Exception e){
            throw new BizSystemException("模型图片写入指定目录时发生错误！");
        }
    }

    private void deleteFile(File file){
        if (file.exists()) {
            // 删除文件
            if (file.delete()) {
                System.out.println("文件删除成功！");
            } else {
                System.out.println("文件删除失败！");
            }
        }
    }

    private void refeshModel(Model model, String filePath){
        if (stableDiffusionApiService.refresh()) {
            String loraSsOutputName = stableDiffusionApiService.getLoraSsOutputName(filePath);
            model.setSsOutputName(loraSsOutputName);
        }
    }

    private void getLabelInfo(List<Model> list){
        List<Long> labelIds = list.stream().map(Model::getLabelId).toList();
        if (CollUtil.isNotEmpty(labelIds)) {
            LambdaQueryWrapper<ModelLabel> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(ModelLabel::getId, labelIds);
            wrapper.eq(ModelLabel::getDelFlag, "0");
            List<ModelLabel> labels = modelLabelService.list(wrapper);
            Map<Long, String> map = labels.stream().collect(Collectors.toMap(ModelLabel::getId, ModelLabel::getLabelName));
            list.forEach(c -> {
                if (null != c.getLabelId() && map.containsKey(c.getLabelId())){
                    c.setLabelName(map.get(c.getLabelId()));
                }
            });
        }
    }

    private ModelTrainParamDto generateModelTrainParam(Map<String, String> map){
        ModelTrainParamDto dto = new ModelTrainParamDto();
        dto.setModel_train_type(map.get("model_train_type"));
        dto.setV2(!map.get("v2").equals("false"));
        dto.setPrior_loss_weight(Integer.parseInt(map.get("prior_loss_weight")));
        dto.setResolution(map.get("resolution"));
        dto.setEnable_bucket(map.get("enable_bucket").equals("true"));
        dto.setMin_bucket_reso(Integer.parseInt(map.get("min_bucket_reso")));
        dto.setMax_bucket_reso(Integer.parseInt(map.get("max_bucket_reso")));
        dto.setBucket_reso_steps(Integer.parseInt(map.get("bucket_reso_steps")));
        dto.setOutput_dir(map.get("output_dir"));
        dto.setSave_model_as(map.get("save_model_as"));
        dto.setSave_precision(map.get("save_precision"));
        dto.setGradient_checkpointing(map.get("gradient_checkpointing").equals("true"));
        dto.setNetwork_train_unet_only(map.get("network_train_unet_only").equals("true"));
        dto.setNetwork_train_text_encoder_only(map.get("network_train_text_encoder_only").equals("true"));
        dto.setLearning_rate(Double.parseDouble(map.get("learning_rate")));
        dto.setUnet_lr(Double.parseDouble(map.get("unet_lr")));
        dto.setText_encoder_lr(Double.parseDouble(map.get("text_encoder_lr")));
        dto.setLr_scheduler(map.get("lr_scheduler"));
        dto.setLr_warmup_steps(Integer.parseInt(map.get("lr_warmup_steps")));
        dto.setLr_scheduler_num_cycles(Integer.parseInt(map.get("lr_scheduler_num_cycles")));
        dto.setOptimizer_type(map.get("optimizer_type"));
        dto.setNetwork_module(map.get("network_module"));
        dto.setNetwork_dim(Integer.parseInt(map.get("network_dim")));
        dto.setNetwork_alpha(Integer.parseInt(map.get("network_alpha")));
        dto.setSample_sampler(map.get("sample_sampler"));
        dto.setSample_every_n_epochs(Integer.parseInt(map.get("sample_every_n_epochs")));
        dto.setSave_every_n_epochs(Integer.parseInt(map.get("save_every_n_epochs")));
        dto.setLog_with(map.get("log_with"));
        dto.setLogging_dir(map.get("logging_dir"));
        dto.setCaption_extension(map.get("caption_extension"));
        dto.setShuffle_caption(map.get("shuffle_caption").equals("true"));
        dto.setKeep_tokens(Integer.parseInt(map.get("keep_tokens")));
        dto.setMax_token_length(Integer.parseInt(map.get("max_token_length")));
        dto.setSeed(Integer.parseInt(map.get("seed")));
        dto.setClip_skip(Integer.parseInt(map.get("clip_skip")));
        dto.setMixed_precision(map.get("mixed_precision"));
        dto.setXformers(map.get("xformers").equals("true"));
        dto.setLowram(map.get("lowram").equals("true"));
        dto.setCache_latents(map.get("cache_latents").equals("true"));
        dto.setCache_latents_to_disk(map.get("cache_latents_to_disk").equals("true"));
        dto.setPersistent_data_loader_workers(map.get("persistent_data_loader_workers").equals("true"));
        return dto;
    }
}